import { useEffect, useState, useRef } from "react";
import { QRCodeCanvas } from "qrcode.react";
import { getLoginQrCodeRequest } from "../services/login/qrcodeLogin";
import { getQrCodeStatusRequest } from "../services/login/getQrCodeStatus";
import { QrCodeStatus } from "../enum";

// 定义二维码数据类型
interface QrCodeData {
  data?: {
    qrId: string;
  };
  expireTime?: string;
}

interface QRCodeLoginProps {
  onSuccess?: (userId: string) => void;
  onRefresh?: () => void;
  isOpen?: boolean;
}

/**
 * 二维码登录组件
 *
 * 展示扫码登录界面，自动获取二维码数据并定时刷新
 * @author BelovedLYC
 */
const QRCodeLogin: React.FC<QRCodeLoginProps> = ({
  onSuccess,
  onRefresh,
  isOpen = true,
}) => {
  // 二维码数据状态
  const [qrData, setQrData] = useState<QrCodeData | null>(null);
  // 加载状态
  const [loading, setLoading] = useState(false);
  // 错误状态
  const [error, setError] = useState<string | null>(null);
  // 二维码状态
  const [qrStatus, setQrStatus] = useState<QrCodeStatus>(QrCodeStatus.PENDING);
  // 上次刷新时间戳，用于防止频繁刷新
  const lastRefreshRef = useRef<number>(0);
  // 最小刷新间隔（毫秒）
  const MIN_REFRESH_INTERVAL = 3000;
  // 二维码过期倒计时（秒）
  const [expiryCountdown, setExpiryCountdown] = useState<number>(0);
  // 倒计时计时器
  const countdownTimerRef = useRef<NodeJS.Timeout | null>(null);

  // 使用refs存储定时器，避免状态更新导致不必要的重渲染
  const expiryTimerRef = useRef<NodeJS.Timeout | null>(null);
  const retryTimerRef = useRef<NodeJS.Timeout | null>(null);
  const pollStatusTimerRef = useRef<NodeJS.Timeout | null>(null);

  // 清除所有定时器的辅助函数
  const clearAllTimers = () => {
    console.log("[QRCode] 执行定时器清理");
    if (expiryTimerRef.current) {
      console.log("[QRCode] 清理过期定时器");
      clearTimeout(expiryTimerRef.current);
      expiryTimerRef.current = null;
    }
    if (retryTimerRef.current) {
      console.log("[QRCode] 清理重试定时器");
      clearTimeout(retryTimerRef.current);
      retryTimerRef.current = null;
    }
    if (pollStatusTimerRef.current) {
      console.log("[QRCode] 清理轮询定时器");
      clearTimeout(pollStatusTimerRef.current);
      pollStatusTimerRef.current = null;
    }
    if (countdownTimerRef.current) {
      console.log("[QRCode] 清理倒计时定时器");
      clearInterval(countdownTimerRef.current);
      countdownTimerRef.current = null;
    }
  };

  // 开始倒计时
  const startCountdown = (expiryTimeMs: number) => {
    // 清除现有倒计时
    if (countdownTimerRef.current) {
      clearInterval(countdownTimerRef.current);
    }

    // 计算初始剩余秒数
    const initialSeconds = Math.max(Math.floor(expiryTimeMs / 1000), 0);
    setExpiryCountdown(initialSeconds);

    // 设置每秒更新的倒计时
    countdownTimerRef.current = setInterval(() => {
      setExpiryCountdown((prevCount) => {
        const newCount = prevCount - 1;
        // 当倒计时归零时，可以停止计时
        if (newCount <= 0) {
          if (countdownTimerRef.current) {
            clearInterval(countdownTimerRef.current);
            countdownTimerRef.current = null;
          }
          return 0;
        }
        return newCount;
      });
    }, 1000);
  };

  // 轮询检查二维码状态
  const pollQrCodeStatus = () => {
    if (!qrData?.data?.qrId) return;

    console.log("[QRCode] 轮询二维码状态:", qrData.data.qrId);

    getQrCodeStatusRequest(qrData.data.qrId)
      .then((response) => {
        if (response.code === 200 && response.data) {
          const status = response.data.status;
          console.log("[QRCode] 二维码状态:", status);

          setQrStatus(status);
          // 根据二维码状态处理不同逻辑
          switch (status) {
            case QrCodeStatus.SCANNED:
              // 已扫描并确认，调用成功回调
              if (onSuccess && response.data.userId) {
                console.log("[QRCode] 登录成功, userId:", response.data.userId);
                onSuccess(response.data.userId);
              } else {
                // 已扫描但未获取到userId，继续轮询
                console.log("[QRCode] 已扫描但未获取到userId，继续轮询");
                pollStatusTimerRef.current = setTimeout(pollQrCodeStatus, 1000);
              }
              break;
            case QrCodeStatus.PENDING:
              // 未扫码，继续轮询
              console.log("[QRCode] 二维码等待扫描，继续轮询");
              pollStatusTimerRef.current = setTimeout(pollQrCodeStatus, 1000);
              break;
            case QrCodeStatus.EXPIRED:
              // 已过期，重新获取二维码
              console.log("[QRCode] 二维码已过期，重新获取");
              fetchQrCode();
              break;
            default:
              // 未知状态，继续轮询
              console.log("[QRCode] 未知状态，继续轮询");
              pollStatusTimerRef.current = setTimeout(pollQrCodeStatus, 1000);
          }
        } else {
          // 请求成功但数据异常，继续轮询
          console.error("[QRCode] 状态检查返回异常:", response.message);
          pollStatusTimerRef.current = setTimeout(pollQrCodeStatus, 3000);
        }
      })
      .catch((err) => {
        console.error("[QRCode] 二维码状态检查失败:", err);
        // 出错后继续轮询
        pollStatusTimerRef.current = setTimeout(pollQrCodeStatus, 3000);
      });
  };

  // 获取二维码数据
  const fetchQrCode = () => {
    // 防止重复请求
    if (loading) {
      return;
    }

    // 检查是否满足最小刷新间隔要求
    const now = Date.now();
    const timeSinceLastRefresh = now - lastRefreshRef.current;
    if (timeSinceLastRefresh < MIN_REFRESH_INTERVAL) {
      console.log(
        `[QRCode] 刷新过于频繁，等待 ${
          (MIN_REFRESH_INTERVAL - timeSinceLastRefresh) / 1000
        } 秒后再试`
      );
      // 设置延迟后再尝试刷新
      expiryTimerRef.current = setTimeout(() => {
        fetchQrCode();
      }, MIN_REFRESH_INTERVAL - timeSinceLastRefresh);
      return;
    }

    // 更新最后刷新时间
    lastRefreshRef.current = now;

    // 清除所有现有定时器
    clearAllTimers();

    // 重置倒计时
    setExpiryCountdown(0);

    // 设置加载状态
    setLoading(true);
    setError(null);
    setQrStatus(QrCodeStatus.PENDING);

    getLoginQrCodeRequest()
      .then((response) => {
        if (response.code === 200 && response.data) {
          // 检查二维码是否有效
          const expireTime = parseInt(response.data.expireTime || "0", 10);
          const currentTime = Date.now();
          const timeUntilExpire = expireTime - currentTime;

          // 记录二维码ID和有效期
          console.log("[QRCode] 获取二维码成功:", response.data);
          console.log("[QRCode] 二维码有效期:", timeUntilExpire, "ms");

          // 只有当二维码有效时才设置
          if (timeUntilExpire > 5000) {
            setQrData(response.data);

            // 启动倒计时显示
            startCountdown(timeUntilExpire);

            // 设置在过期前提前刷新
            // 确保至少有5秒的有效期，避免过快刷新
            expiryTimerRef.current = setTimeout(() => {
              console.log("[QRCode] 二维码即将过期，自动刷新");
              fetchQrCode();
            }, timeUntilExpire - 5000); // 提前5秒刷新

            // 启动轮询检查状态
            pollQrCodeStatus();
          } else {
            // 二维码已经过期或即将过期，延迟后重新获取
            console.log("[QRCode] 获取的二维码有效期太短，延迟后重新获取");
            retryTimerRef.current = setTimeout(() => {
              fetchQrCode();
            }, 3000);
          }
        } else {
          setError(response.message || "获取二维码失败");
          console.error("[QRCode] 获取二维码失败:", response.message);

          // 出错后3秒重试
          retryTimerRef.current = setTimeout(() => {
            console.log("[QRCode] 3秒后重试获取二维码");
            fetchQrCode();
          }, 3000);
        }
      })
      .catch((err) => {
        console.error("[QRCode] 二维码获取网络错误:", err);
        setError("网络错误，请稍后再试");

        // 出错后3秒重试
        retryTimerRef.current = setTimeout(() => {
          console.log("[QRCode] 网络错误3秒后重试");
          fetchQrCode();
        }, 3000);
      })
      .finally(() => {
        // 只有在没有设置新的定时器时才重置loading状态
        setLoading(false);
      });
  };

  // 监听isOpen属性变化，当组件隐藏时停止所有轮询
  useEffect(() => {
    console.log("[QRCode] isOpen变化:", isOpen);
    if (isOpen) {
      // 组件可见时，启动二维码获取
      console.log("[QRCode] 组件显示，开始获取二维码");
      fetchQrCode();
    } else {
      // 组件不可见时，清除所有定时器
      console.log("[QRCode] 组件隐藏，清除所有定时器");
      clearAllTimers();
    }

    // 组件卸载或隐藏时清除所有定时器
    return () => {
      console.log("[QRCode] useEffect清理函数执行");
      clearAllTimers();
    };
  }, [isOpen]);

  // 组件卸载时确保清理所有定时器
  useEffect(() => {
    return () => {
      console.log("[QRCode] 组件卸载，执行最终清理");
      clearAllTimers();
    };
  }, []);

  // 处理刷新按钮点击
  const handleRefresh = () => {
    console.log("[QRCode] 用户点击刷新按钮");
    fetchQrCode();
    // 如果传入了onRefresh回调，也调用它
    if (onRefresh) {
      onRefresh();
    }
  };

  return (
    <div className="flex flex-col items-center justify-center py-8 px-4">
      <div className="bg-white dark:bg-gray-700 p-4 rounded-xl shadow-md mb-6 relative">
        {/* 二维码区域 */}
        {loading && !qrData ? (
          // 初始加载状态 - 仅在没有数据时显示
          <div className="w-52 h-52 bg-gray-100 dark:bg-gray-600 flex items-center justify-center">
            <svg
              className="animate-spin h-10 w-10 text-blue-500"
              xmlns="http://www.w3.org/2000/svg"
              fill="none"
              viewBox="0 0 24 24"
            >
              <circle
                className="opacity-25"
                cx="12"
                cy="12"
                r="10"
                stroke="currentColor"
                strokeWidth="4"
              ></circle>
              <path
                className="opacity-75"
                fill="currentColor"
                d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
              ></path>
            </svg>
          </div>
        ) : error && !qrData ? (
          // 错误状态 - 仅在没有数据时显示
          <div className="w-52 h-52 bg-gray-100 dark:bg-gray-600 flex flex-col items-center justify-center p-4">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              className="h-12 w-12 text-red-500 mb-2"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
              />
            </svg>
            <p className="text-center text-sm text-red-600 dark:text-red-400">
              {error}
            </p>
          </div>
        ) : qrData ? (
          <>
            <QRCodeCanvas
              value={qrData?.data?.qrId || ""}
              size={208}
              level="H"
              includeMargin={true}
              className={`rounded-md ${
                qrStatus === QrCodeStatus.SCANNED ? "opacity-50" : ""
              }`}
            />
            {/* 倒计时显示 */}
            {expiryCountdown > 0 && (
              <div className="absolute top-2 right-2 bg-black bg-opacity-70 text-white text-xs font-medium rounded-full px-2 py-1">
                {expiryCountdown}s
              </div>
            )}
            {qrStatus === QrCodeStatus.SCANNED && (
              <div className="absolute inset-0 flex items-center justify-center bg-black bg-opacity-20 rounded-md">
                <div className="bg-white dark:bg-gray-800 p-3 rounded-lg shadow-lg">
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    className="h-8 w-8 text-green-500 mx-auto"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth={2}
                      d="M5 13l4 4L19 7"
                    />
                  </svg>
                  <p className="text-center mt-2 text-sm font-medium">
                    已扫描，请在手机上确认
                  </p>
                </div>
              </div>
            )}
          </>
        ) : (
          // 空状态 (不应该出现)
          <div className="w-52 h-52 bg-gray-100 dark:bg-gray-600 flex items-center justify-center">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              className="h-24 w-24 text-gray-400 dark:text-gray-500"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={1.5}
                d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm12 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z"
              />
            </svg>
          </div>
        )}

        {/* 刷新按钮 */}
        <button
          onClick={handleRefresh}
          disabled={loading}
          className={`absolute -bottom-3 right-1/2 transform translate-x-1/2 bg-white dark:bg-gray-800 rounded-full p-2 shadow-md transition-all ${
            loading
              ? "opacity-50 cursor-not-allowed"
              : "hover:shadow-lg hover:bg-gray-50 dark:hover:bg-gray-700"
          }`}
          title="刷新二维码"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            className={`h-5 w-5 text-gray-500 dark:text-gray-400 ${
              loading ? "animate-spin" : ""
            }`}
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
            />
          </svg>
        </button>
      </div>

      {/* 提示文字 */}
      <p className="text-center text-gray-600 dark:text-gray-300">
        请使用APP扫描二维码登录
      </p>
      <p className="text-center text-sm text-gray-500 dark:text-gray-400 mt-2">
        {qrStatus === QrCodeStatus.SCANNED
          ? "已扫描，请在手机上确认"
          : "扫码后请在手机上确认登录"}
      </p>
    </div>
  );
};

export default QRCodeLogin;
